import dayjs from "dayjs";
import * as constants from '@/common/constants'
import { Loading, Message } from 'element-ui';
import {
  createStore,
  addStoreValue,
  deleteStore,
} from "./indexedDB";

// $utils
/** 获取当前时间 */
export function getCurrentTime() {
  return dayjs(Date.now()).format("YYYY-MM-DD HH:mm:ss")
}
/** 休眠 */
export function sleep(timeout = 500) {
  return new Promise(resolve => setTimeout(resolve, timeout))
}
/** loading */
export function loading({ text = "加载中...", fn }) {
  return new Promise(async resolve => {
    const loading = Loading.service({
      lock: true,
      text,
      spinner: "el-icon-loading",
      background: "rgba(0, 0, 0, 0.7)",
    });
    const result = fn()
    await sleep()
    loading.close()
    resolve(result)
  })
}
/** loading */
export async function loading1(fn, text = "加载中...") {
  const loading = Loading.service({
    lock: true,
    text,
    spinner: "el-icon-loading",
    background: "rgba(0, 0, 0, 0.7)",
  });
  fn()
  await sleep()
  loading.close()
}

// $文件处理
/** 获取文件内容 */
export function getFileContent(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsText(file);
    reader.onload = (e) => resolve(e.target.result)
    reader.onerror = reject
  })
}
/** 获取文件流 */
export function getFileStream(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (e) => resolve(e.target.result)
    reader.onerror = reject
  })
}
/** json转blob url */
export function jsonToBlobUrl(json) {
  const blob = new Blob([json], { type: "application/json" });
  return URL.createObjectURL(blob);
}
/** 下载文件 */
export function downloadFile(name, file) {
  const a = document.createElement('a')
  a.download = name
  a.href = file
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}
// $项目文件
/** 检查项目文件类型 */
export function checkProjectFileType(file) {
  const type = file.name.slice(file.name.lastIndexOf(".") + 1).toLocaleLowerCase()
  if (type !== constants.PROJECT_SUFFIX) {
    Message.warning(`请导入${constants.PROJECT_SUFFIX}类型的文件`);
    return false
  }
  return true
}
/** 获取项目文件内容 */
export function getProjectFileContent(file) {
  return new Promise(async (resolve) => {
    try {
      const content = await getFileContent(file)
      resolve({ code: 200, msg: '读取成功', data: JSON.parse(content) })
    } catch (e) {
      resolve({ code: 500, msg: '文件内容格式错误', e })
    }
  })
}

// $PDF文件
/** 检查PDF文件类型 */
export function checkPDFFileType(file) {
  const type = file.name.slice(file.name.lastIndexOf(".") + 1);
  if (type.toLocaleUpperCase() !== 'PDF') {
    Message.warning("请上传pdf类型的文件");
    return false
  }
  return true
}
/** 
 * 获取PDF文件信息
 * @param {string| File} file 文件/文件地址
 * @returns {PDFDocumentProxy} PDF对象
 */
export function getPDFData(file) {
  return new Promise(async (resolve, reject) => {
    const fileStream = file instanceof File ? await getFileStream(file) : file
    pdfjsLib.getDocument(fileStream).promise
      .then((pdf) => resolve(pdf))
      .catch(reject)
  })
}

// $手写码Key文件及Key处理
/** 检查手写码Key文件类型 */
export function checkWriteKeyFileType(file) {
  const type = file.name.slice(file.name.lastIndexOf(".") + 1);
  if (type.toLocaleUpperCase() !== 'TMX') {
    Message.warning("请上传tmx类型的文件");
    return false
  }
  return true
}
/** 读取手写码Key值 */
export function getWriteKey(file) {
  return new Promise(async resolve => {
    const fileContent = await getFileContent(file.file)
    const result = parseWriteKey(fileContent)
    resolve(result)
  })
}
/** 解析手写码Key */
export function parseWriteKey(writeKey) {
  const value = writeKey.match().input.replace(/\r\n/g, "")
  const [sid, oid, bid, pid, expiryDate] = value.split(";")[0].split(",").map((i) => i.slice(1));
  const [minPid, maxPid] = pid.split("-").map(i => Number(i))
  return {
    sid: Number(sid),
    oid: Number(oid),
    bid: Number(bid),
    minPid,
    maxPid,
    expiryDate,
    value
  }
}
/** 校验手写码Key (Element-Form) */
export function checkWriteCodeKey(rule, value, callback) {
  const { expiryDate, maxPid } = value;
  if (new Date(expiryDate).getTime() < Date.now()) {
    return callback(new Error("手写码Key已过期！"));
  }
  if (maxPid > 255) {
    return callback(new Error("pid最大为255"));
  }
  return callback();
}

// $点读码Key文件及Key处理
/** 检查点读码Key文件类型 */
export function checkReadKeyFileType(file) {
  const type = file.name.slice(file.name.lastIndexOf(".") + 1);
  if (type.toLocaleUpperCase() !== 'TMXE') {
    Message.warning("请上传tmxe类型的文件");
    return false
  }
  return true
}
/** 读取点读码Key值 */
export function getReadKey(file) {
  return new Promise(async (resolve) => {
    const fileContent = await getFileContent(file.file)
    const result = parseReadKey(fileContent)
    resolve(result)
  })
}
/** 解析点读码Key */
export function parseReadKey(readKey) {
  const value = readKey.match().input.replace(/\r\n/g, "");
  const [sa, sb, sc, sd, index, expiryDate] = value.split(";")[0].split(",").map((i) => i.slice(1));
  const [minIndex, maxIndex] = index.split("-").map(i => Number(i))
  return {
    sa: Number(sa.slice(1)),
    sb: Number(sb.slice(1)),
    sc: Number(sc.slice(1)),
    sd: Number(sd.slice(1)),
    minIndex,
    maxIndex,
    expiryDate,
    value
  }
}
/** 校验点读码Key (Element-Form) */
export function checkReadCodeKey(rule, value, callback) {
  const { expiryDate } = value;
  if (new Date(expiryDate).getTime() < Date.now()) {
    return callback(new Error("点读码Key已过期！"));
  }
  return callback();
}

//  $码点数据处理
/** 保留小数点后两位 */
export function toFixed(number) {
  return parseFloat(number.toFixed(2));
}
/** 像素转实际大小 pdf-dist.js 生成DPI为72的图片 */
export function pxToActualSize(px) {
  return toFixed(px / (72 / 25.4));
}

/** 像素转码点坐标 pdf-dist.js 生成DPI为72的图片 */
export function pxToCodeSize(px, distance) {
  return toFixed(px / 72 * 25.4 / distance);
}

/** 点读码实际值 */
export function readCodeRealValue(readcode) {
  return readcode.index + (65535 * (readcode.sd + (readcode.sc * Math.pow(256, 1)) + (readcode.sb * Math.pow(256, 2)) + (readcode.sa * Math.pow(256, 3))))
}


/** 生成项目 */
export function generateProject(data) {
  const result = (code, msg = null) => ({ code, msg })
  return new Promise(async resolve => {
    const keys = Object.keys(data).map((i) => (Number(i) ? Number(i) : i));
    // 创建数据库
    const createStoreResult = await createStore(data.name);
    if (createStoreResult.code !== 200) {
      return resolve(result(500, "创建数据库失败！"))
    }
    // 向数据库添加数据
    const addValueResult = await Promise.all(
      keys.map((i) => addStoreValue(data.name, i, data[i]))
    );
    if (!addValueResult.every((i) => i.code === 200)) {
      await deleteStore(data.name)
      return resolve(result(500, "添加数据失败，请重试！"))
    }
    resolve(result(200))
  })
}
